package com.miguo.framework.web;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.webkit.CookieManager;
import android.webkit.WebSettings;
import android.webkit.WebView;

import com.miguo.framework.utils.Log;
import com.miguo.framework.utils.Version;
import com.miguo.framework.web.utils.WebUtils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * A convenient extension of WebView.
 */
public class CustomWebView extends WebView {

    private static boolean mBoMethodsLoaded = false;
    private static Method mNotifyFindDialogDismissed = null;
    private static Method mOnPauseMethod = null;
    private static Method mOnResumeMethod = null;
    private static Method mSetFindIsUp = null;
    private WebSettings settings;
    private Context mContext;
    private String mLoadedUrl;
    // private String USER_AGENT_DESKTOP =
    // "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.517.44 Safari/534.7";
    private int mProgress = 100;
    private boolean mIsLoading = false;

    /**
     * Constructor.
     *
     * @param context The current context.
     */
    public CustomWebView(Context context) {
        super(context);
        mContext = context;
        initializeOptions();
        loadMethods();
    }

    /**
     * Constructor.
     *
     * @param context The current context.
     * @param attrs   The attribute set.
     */
    public CustomWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        initializeOptions();
        loadMethods();
    }

    /**
     * Initialize the WebView with the options set by the user through
     * preferences.
     */
    public void initializeOptions() {
        settings = getSettings();
        settings.setJavaScriptCanOpenWindowsAutomatically(true);
        settings.setAllowFileAccess(true);
        settings.setJavaScriptEnabled(true);
        settings.setUseWideViewPort(true);
        settings.setLoadWithOverviewMode(true);
        settings.setSaveFormData(true);
        CookieManager.getInstance().setAcceptCookie(true);
        settings.setSupportZoom(true);
        settings.setSupportMultipleWindows(true);

        if (Version.hasKitKat() == true) {
            settings.setLoadsImagesAutomatically(true);
        } else {
            settings.setLoadsImagesAutomatically(false);
        }

        setLongClickable(true);
        setScrollbarFadingEnabled(true);
        setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
        settings.setAppCacheEnabled(true);
        settings.setAppCachePath(WebUtils.getCacheDirectory(mContext)
                .getAbsolutePath());
        settings.setDatabaseEnabled(true);
        settings.setDomStorageEnabled(true);
        // 设置浏览器标识(UA)
        // String user_agent=settings.getUserAgentString();
        // settings.setUserAgentString(user_agent);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        final int action = ev.getAction();

        // Enable / disable zoom support in case of multiple pointer, e.g.
        // enable zoom when we have two down pointers, disable with one pointer
        // or when pointer up.
        // We do this to prevent the display of zoom controls, which are not
        // useful and override over the right bubble.
        if ((action == MotionEvent.ACTION_DOWN)
                || (action == MotionEvent.ACTION_POINTER_DOWN)) {
            if (ev.getPointerCount() > 1) {
                this.getSettings().setBuiltInZoomControls(true);
                this.getSettings().setSupportZoom(true);
            } else {
                this.getSettings().setBuiltInZoomControls(false);
                this.getSettings().setSupportZoom(false);
            }
        } else if ((action == MotionEvent.ACTION_UP)
                || (action == MotionEvent.ACTION_POINTER_UP)) {
            this.getSettings().setBuiltInZoomControls(false);
            this.getSettings().setSupportZoom(false);
        }

        return super.onTouchEvent(ev);
    }

    @Override
    public void loadUrl(String url) {
        url = WebUtils.DefaultUrlParam(url);
        mLoadedUrl = url;
        super.loadUrl(url);
    }

    /**
     * Set the current loading progress of this view.
     *
     * @param progress The current loading progress.
     */
    public void setProgress(int progress) {
        mProgress = progress;
    }

    /**
     * Get the current loading progress of the view.
     *
     * @return The current loading progress of the view.
     */
    public int getProgress() {
        return mProgress;
    }

    /**
     * Triggered when a new page loading is requested.
     */
    public void notifyPageStarted() {
        mIsLoading = true;
    }

    /**
     * Triggered when the page has finished loading.
     */
    public void notifyPageFinished() {
        mProgress = 100;
        mIsLoading = false;
        if (!settings.getLoadsImagesAutomatically()) {
            settings.setLoadsImagesAutomatically(true);
        }
    }

    /**
     * Check if the view is currently loading.
     *
     * @return True if the view is currently loading.
     */
    public boolean isLoading() {
        return mIsLoading;
    }

    /**
     * Get the loaded url, e.g. the one asked by the user, without redirections.
     *
     * @return The loaded url.
     */
    public String getLoadedUrl() {
        return mLoadedUrl;
    }

    /**
     * Reset the loaded url.
     */
    public void resetLoadedUrl() {
        mLoadedUrl = null;
    }

    public boolean isSameUrl(String url) {
        if (url != null) {
            return url.equalsIgnoreCase(this.getUrl());
        }

        return false;
    }

    /**
     * Perform an 'onPause' on this WebView through reflexion.
     */
    public void doOnPause() {
        if (mOnPauseMethod != null) {
            try {
                mOnPauseMethod.invoke(this);
            } catch (IllegalArgumentException e) {
                Log.e("doOnPause(): " + e.getMessage());
            } catch (IllegalAccessException e) {
                Log.e("doOnPause(): " + e.getMessage());
            } catch (InvocationTargetException e) {
                Log.e("doOnPause(): " + e.getMessage());
            }
        }
    }

    /**
     * Perform an 'onResume' on this WebView through reflexion.
     */
    public void doOnResume() {
        if (mOnResumeMethod != null) {
            try {

                mOnResumeMethod.invoke(this);

            } catch (IllegalArgumentException e) {
                Log.e("doOnResume(): " + e.getMessage());
            } catch (IllegalAccessException e) {
                Log.e("doOnResume(): " + e.getMessage());
            } catch (InvocationTargetException e) {
                Log.e("doOnResume(): " + e.getMessage());
            }
        }
    }

    public void doSetFindIsUp(boolean value) {
        if (mSetFindIsUp != null) {
            try {

                mSetFindIsUp.invoke(this, value);

            } catch (IllegalArgumentException e) {
                Log.e("doSetFindIsUp(): " + e.getMessage());
            } catch (IllegalAccessException e) {
                Log.e("doSetFindIsUp(): " + e.getMessage());
            } catch (InvocationTargetException e) {
                Log.e("doSetFindIsUp(): " + e.getMessage());
            }
        }
    }

    public void doNotifyFindDialogDismissed() {
        if (mNotifyFindDialogDismissed != null) {
            try {

                mNotifyFindDialogDismissed.invoke(this);

            } catch (IllegalArgumentException e) {
                Log.e("doNotifyFindDialogDismissed(): " + e.getMessage());
            } catch (IllegalAccessException e) {
                Log.e("doNotifyFindDialogDismissed(): " + e.getMessage());
            } catch (InvocationTargetException e) {
                Log.e("doNotifyFindDialogDismissed(): " + e.getMessage());
            }
        }
    }

    /**
     * Load static reflected methods.
     */
    private void loadMethods() {

        if (!mBoMethodsLoaded) {

            try {

                mOnPauseMethod = WebView.class.getMethod("onPause");
                mOnResumeMethod = WebView.class.getMethod("onResume");

            } catch (SecurityException e) {
                Log.e("loadMethods(): " + e.getMessage());
                mOnPauseMethod = null;
                mOnResumeMethod = null;
            } catch (NoSuchMethodException e) {
                Log.e("loadMethods(): " + e.getMessage());
                mOnPauseMethod = null;
                mOnResumeMethod = null;
            }

            try {

                mSetFindIsUp = WebView.class.getMethod("setFindIsUp",
                        Boolean.TYPE);
                mNotifyFindDialogDismissed = WebView.class
                        .getMethod("notifyFindDialogDismissed");

            } catch (SecurityException e) {
                Log.e("loadMethods(): " + e.getMessage());
                mSetFindIsUp = null;
                mNotifyFindDialogDismissed = null;
            } catch (NoSuchMethodException e) {
                Log.e("loadMethods(): " + e.getMessage());
                mSetFindIsUp = null;
                mNotifyFindDialogDismissed = null;
            }
            mBoMethodsLoaded = true;
        }
    }

}
